#include <stdio.h>
#include <spu_intrinsics.h>
#include <spu_mfcio.h>
#include "cmatrixprod.h"



/* Variables Globales */

#define MAX_BUFSIZE (128)

t_complex in_A[MAX_BUFSIZE] __attribute__((aligned(16)));
t_complex in_B[MAX_BUFSIZE] __attribute__((aligned(16)));
t_complex out_C[MAX_BUFSIZE] __attribute__((aligned(16)));

abs_params_t abs_params __attribute__((aligned(16)));



/* Fonction d'affichage */

void affiche(t_complex a[], int nlig, int ncol, char *s)
{
  int i,j;
  printf("__SPE\n\n%s=[\n",s);
  
  for (i=0; i<nlig;i++) {
    for (j=0;j<ncol;j++) 
      printf("%f + %f*i  ",a[i*ncol+j].r,a[i*ncol+j].i);
    printf(";\n"); 
  }   
 printf("];\n");
}


/* Fonction de calculation de multiplication complexe */

void calculation(int M, int N, int P, t_complex *A, 
		 t_complex *B, t_complex *C){
  
  int i,j,k;
  t_complex som;
  
  for(i=0;i<M;i++){
    for (j=0;j<N;j++){
      som=C[i*N+j];
      for (k=0;k<P;k++) {
	som.r = som.r + A[i*P+k].r*B[k*N+j].r-A[i*P+k].i*B[k*N+j].i;
	som.i = som.i + A[i*P+k].r*B[k*N+j].i+A[i*P+k].i*B[k*N+j].r;
      }
      C[i*N+j]=som;
    }
  }
}  



int main(unsigned long long spe, unsigned long long argp, unsigned long long envp)
{
  int tag = 0;
  int tid = 0, rid = 0;
  unsigned int res;
  

  printf("__SPE - lancé\n");
  
  /* Types vecteurs pour tout-à-l'heure ... */
  /* vector float *vin  = (vector float *) in_spe; */
  /* vector float *vout = (vector float *) out_spe; */
  
  printf("__SPE - get abs_params\n");
  
  /* DMA Transfer 1 : GET input/output parameters */
  mfc_get(&abs_params, argp, sizeof(abs_params_t), tag, tid, rid);
  mfc_write_tag_mask(1<<tag);
  res = mfc_read_tag_status_all();
  
  printf("__SPE - get A\n");
  
  /* DMA Transfer 2 : GET Matrix A */
  mfc_get(in_A, abs_params.in_matrix_A, abs_params.size_M * abs_params.size_N * sizeof(t_complex), tag, tid, rid);
  mfc_write_tag_mask(1<<tag);
  mfc_read_tag_status_all();
  
  printf("__SPE - get B\n");
  
  /* DMA Transfer 3 : GET Matrix B */
  mfc_get(in_B, abs_params.in_matrix_B, abs_params.size_N * abs_params.size_P * sizeof(t_complex), tag, tid, rid);
  mfc_write_tag_mask(1<<tag);
  mfc_read_tag_status_all();
  
  printf("__SPE - get C\n");
  
  /* DMA Transfer 4 : GET Matrix C */
  mfc_get(out_C, abs_params.out_matrix_C, abs_params.size_M * abs_params.size_P * sizeof(t_complex), tag, tid, rid);
  mfc_write_tag_mask(1<<tag);
  mfc_read_tag_status_all();
  
  printf("__SPE - calcul\n");
  
  /* Calcul de la multiplication */
  calculation(abs_params.size_M,abs_params.size_N,abs_params.size_P, in_A, in_B, out_C);
  
  printf("__SPE - écrit résultat\n");
  
  /* DMA Transfer 5 : PUT output data */
  mfc_put(out_C, abs_params.out_matrix_C,abs_params.size_M * abs_params.size_P * sizeof(t_complex), tag, tid, rid);
  mfc_write_tag_mask(1<<tag);
  mfc_read_tag_status_all();

  return 0;
}












//// ANCIEN CODE DE CALCUL DE VALEUR ABSOLUE   ////

    /* /\* Calculate absolute values with vector operation *\/ */
/*     for (i = 0; i < abs_params.size/4; i++) { */
/*       /\* STEP1: find all values > 0 the vector vin[i] with spu_cmpgt *\/ */
      
/*       zero = spu_splats(0.0f); */
/*       moinsun = spu_splats(-1.0f); */
/*       cmp = spu_cmpgt(vin[i],zero); */
/*       neg = spu_mul(moinsun,vin[i]); */
/*       vout[i] = spu_sel(neg,vin[i],cmp); */
      

/*       /\* STEP2: change the sign of all values in vin[i] with spu_mul *\/ */
/*       /\* ......... TODO .......... *\/ */
/*       /\* STEP3: use STEP1 and STE2 and spu_sel *\/ */
/*     } */
